package info.emamian.droplet.web.controllers;

import info.emamian.droplet.aws.SQSService;
import info.emamian.droplet.controllers.AbstractDroppletWebController;
import info.emamian.droplet.data.DynamoDbClientFactory;
import info.emamian.droplet.data.DynamoDbSms;
import info.emamian.droplet.data.DynamoDbSmsService;
import info.emamian.droplet.data.SystemEventsDynamoDB;
import info.emamian.droplet.provider.InputSMSAdaptorInterface;
import info.emamian.droplet.provider.TwilioAdaptor;

import java.util.Date;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;

@Controller
@RequestMapping(value = "/sms")
public class SMSController extends AbstractDroppletWebController {
	private static final Logger LOGGER = LoggerFactory
			.getLogger(SMSController.class);

	private static Long CONTROLLER_COUNT = 0L;
	private static long duration_sum = 0;
	private static long duration_count = 0;
	private long web_id;
	private DynamoDBMapper dbMapper = DynamoDbClientFactory
			.getDBMapperInstance();

	@Autowired
	DynamoDbSmsService dynamoDbSmsService;

	@Autowired
	SQSService sqsService;

	@Autowired
	TwilioAdaptor twilioAdaptor;

	@PostConstruct
	public void postConstruct() {
		synchronized (CONTROLLER_COUNT) {
			CONTROLLER_COUNT++;
			this.web_id = CONTROLLER_COUNT.longValue();
		}
		try {
			SystemEventsDynamoDB ev = new SystemEventsDynamoDB();
			ev.setDate(new Date());
			ev.setMessageType("web");
			ev.setMessage("web " + this.web_id + " created");
			getDbMapper().save(ev);
		} catch (Exception e) {
			LOGGER.error("Exception , ", e);
		}
		LOGGER.info("--postConstruct: web {} created.", this.web_id);
	}

	@PreDestroy
	public void finalStatistics() {
		if (duration_count > 0) {
			LOGGER.info(String.format("request count [%s], avg duration [%s]",
					duration_count, (duration_sum / duration_count)));
		}
		try {
			SystemEventsDynamoDB ev = new SystemEventsDynamoDB();
			ev.setDate(new Date());
			ev.setMessageType("web");
			ev.setMessage("web " + this.web_id + " destroyed");
			getDbMapper().save(ev);
		} catch (Exception e) {
			LOGGER.error("Exception , ", e);
		}

	}

	@RequestMapping("/twilio")
	public void twilioRequestHandler(final HttpServletRequest req,
			final HttpServletResponse resp) {
		try {

			long start_time = System.currentTimeMillis();
			handleRequest(req, resp, twilioAdaptor);
			long end_time = System.currentTimeMillis();
			logDuration(start_time, end_time);

		} catch (Exception e) {
			// TODO: handle exception
			LOGGER.error("Exception handling twilio, ", e);
		}
	}

	private static void logDuration(final long start_time, final long end_time) {
		duration_sum += end_time - start_time;
		duration_count++;
		if (duration_count % 100 == 99) {
			LOGGER.info("Response count [{}]. avg duration:[{}]",
					duration_count, (duration_sum / duration_count));
		}
	}

	private void handleRequest(final HttpServletRequest req,
			final HttpServletResponse resp,
			final InputSMSAdaptorInterface InputSMSAdaptor) {

		try {
			if (InputSMSAdaptor == null) {
				throw new Exception("inputSmsAdaptor cannot be null");
			}
			DynamoDbSms converted = InputSMSAdaptor.convertToDynamoDbSMS(req);
			dynamoDbSmsService.save(converted);
			addToInputQueue(converted);
			// resp.getWriter().write("done and done");
			resp.setStatus(HttpStatus.OK.value());
		} catch (Exception e) {
			LOGGER.error("Exception handling request , ", e);
			resp.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());// 500
		}
	}

	private void addToInputQueue(final DynamoDbSms converted) {
		try {
			// sqsService.sendMessage(converted.getId());
		} catch (Exception e) {
			LOGGER.error("Exception sending Message, ", e);
		}
	}

	public DynamoDBMapper getDbMapper() {
		return dbMapper;
	}

	public void setDbMapper(final DynamoDBMapper dbMapper) {
		this.dbMapper = dbMapper;
	}

}
